// 响应式系统
const targetMap = new WeakMap(); // 存储依赖关系的全局变量
let activeEffect = null; // 当前激活的副作用函数 effect
const effectStack = []; // 副作用函数栈,用于处理嵌套的 effect

// 深度遍历对象，收集所有嵌套属性的依赖
function traverse(value, seen = new Set()) {
  if (!isObject(value) || value === null || seen.has(value)) {
    return value
  }
  
  seen.add(value)
  
  if (Array.isArray(value)) {
    for (let i = 0; i < value.length; i++) {
      traverse(value[i], seen)
    }
  } else {
    for (const key in value) {
      traverse(value[key], seen)
    }
  }
  
  return value
}

// 工具函数
function isObject(val) {
  return val !== null && typeof val === 'object'
}

function isRef(ref) {
  return ref && ref.__v_isRef === true
}

function isReactive(value) {
  return value && value.__v_isReactive === true
}

// 增强我们的响应式系统，添加标记
function reactive(target) {
  const proxy = new Proxy(target, {
    get(target, key, receiver) {
      if (key === '__v_isReactive') return true
      
      console.log(`🔍 读取属性: ${String(key)} = ${target[key]}`)
      const result = Reflect.get(target, key, receiver)
      track(target, key)
      
      if (typeof result === 'object' && result !== null) {
        return reactive(result)
      }
      
      return result
    },
    set(target, key, value, receiver) {
      console.log(`✏️ 设置属性: ${String(key)} = ${value}`)
      const oldValue = target[key]
      const result = Reflect.set(target, key, value, receiver)
      
      if (oldValue !== value) {
        trigger(target, key)
      }
      
      return result
    }
  })
  return proxy
}

// 增强 ref 实现
function ref(value) {
  const refObject = {
    __v_isRef: true,
    get value() {
      track(refObject, 'value')
      return value
    },
    set value(newVal) {
      if (value !== newVal) {
        value = newVal
        trigger(refObject, 'value')
      }
    }
  }
  return refObject
}

// 增强 effect，支持停止和懒加载
function effect(fn, options = {}) {
  let effectFn = () => {
    try {
      effectStack.push(effectFn)
      activeEffect = effectFn
      return fn()
    } finally {
      effectStack.pop()
      activeEffect = effectStack[effectStack.length - 1]
    }
  }
  
  effectFn.scheduler = options.scheduler
  effectFn.lazy = options.lazy
  
  // 停止函数
  effectFn.stop = () => {
    // 从所有依赖中移除这个 effect
    if (effectFn.deps) {
      effectFn.deps.forEach(dep => dep.delete(effectFn))
    }
  }
  
  effectFn.deps = [] // 存储这个 effect 的所有依赖集合
  
  if (!options.lazy) {
    effectFn()
  }
  
  return effectFn
}

// 增强 track 函数，记录 effect 的依赖
function track(target, key) {
  if (!activeEffect) return
  
  let depsMap = targetMap.get(target)
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()))
  }
  
  let dep = depsMap.get(key)
  if (!dep) {
    depsMap.set(key, (dep = new Set()))
  }
  
  if (!dep.has(activeEffect)) {
    dep.add(activeEffect)
    // 记录这个依赖集合到 effect 中
    activeEffect.deps.push(dep)
  }
}
// 派发更新
function trigger(target, key) {
    // 获取target对应的依赖集合
    const depsMap = targetMap.get(target);
    if (!depsMap) return;

    // 获取key对应的依赖集合
    const dep = depsMap.get(key);
    if (!dep) return;
    console.log(`🚀 触发更新: ${String(key)}，共有 ${dep.size} 个依赖`);

    // 创建一个Set，用于存储需要执行的effect,避免重复执行
    const effectsToRun = new Set();
    // 遍历依赖集合，执行每个effect
    dep.forEach((effect) => {
        effectsToRun.add(effect);
    });
    effectsToRun.forEach((effect) => {
        if (effect.scheduler) {
            // 如果有调度器，则使用调度器执行effect，调度器主要用于异步更新页面
            effect.scheduler();
        } else {
            // 否则直接执行effect
            effect();
        }
    });
}

// 6. computed 实现
function computed(getter) {
    let dirty = true; // 是否需要重新计算
    let value; // 计算属性的值
    let computedRef = ref(); // 计算属性的引用对象

    /**
     *例子： getter:()=>count.value*2;
     * lazy为true，所以刚创建computed的时候，不会立即执行getter函数，而是将getter函数赋值给computedRef.value，
     * 当访问computedRef.value的时候，dirty为ture,触发runner函数(getter)，getter函数读取了count.value,
     * count对应的track会收集依赖activeEffect，
     * 而此时的activeEffect是包含getter的effectFn和对应的scheduler
     * 当count.value改变的时候，会触发trigger，从而执行scheduler，scheduler中会判断dirty，
     * 如果dirty为true，则执行runner函数，
     */
    const runner = effect(getter, {
        lazy: true, // 懒执行
        scheduler: () => {
            // 调度器的作用：
            if (!dirty) {
                dirty = true;
                trigger(computedRef, "value");
            }
        },
    });

    //将 runner 函数赋值给 computedRef.value，以便在访问 computedRef.value 时执行 runner 函数
    Object.defineProperty(computedRef, "value", {
        get() {
            if (dirty) {
                value = runner();
                dirty = false;
                track(computedRef, "value");
            }
            return value;
        },
    });
    return computedRef;
}

// 基于之前的响应式系统实现 watch
function watch(source, cb, options = {}) {
  let getter
  let oldValue
  let cleanup // 清理函数

  // 1. 标准化 source - 支持多种形式
  if (typeof source === 'function') {
    getter = source
  } else if (isRef(source)) {
    getter = () => source.value
  } else if (isReactive(source)) {
    getter = () => source
    // 默认深度监听 reactive 对象
    options.deep = options.deep !== false
  } else if (Array.isArray(source)) {
    // 支持监听数组
    getter = () => source.map(s => {
      if (typeof s === 'function') {
        return s()
      } else if (isRef(s)) {
        return s.value
      } else if (isReactive(s)) {
        return traverse(s)
      }
    })
  } else {
    console.warn('Invalid watch source:', source)
    return
  }

  // 2. 处理深度监听
  if (options.deep) {
    const baseGetter = getter
    getter = () => traverse(baseGetter())
  }

  // 3. 清理函数注册
  const onInvalidate = (fn) => {
    cleanup = fn
  }

  // 4. 调度函数 - 控制执行时机
  const job = () => {
    const newValue = effectFn()
    
    // 先执行清理函数
    if (cleanup) {
      cleanup()
      cleanup = null
    }
    
    // 执行回调
    cb(newValue, oldValue, onInvalidate)
    oldValue = newValue
  }

  // 5. 创建 effect
  const effectFn = effect(
    () => getter(),
    {
      lazy: true, // 懒执行，手动调用获取初始值
      scheduler: () => {
        if (options.flush === 'sync') {
          // 同步执行
          job()
        } else if (options.flush === 'post') {
          // 后置执行 - 类似 nextTick
          Promise.resolve().then(job)
        } else {
          // 默认 - 异步队列
          job()
        }
      }
    }
  )

  // 6. 初始化
  if (options.immediate) {
    // 立即执行回调
    job()
  } else {
    // 获取初始值
    oldValue = effectFn()
  }

  // 7. 返回停止函数
  return () => {
    effectFn.stop && effectFn.stop()
  }
}

// 测试用例
console.log('=== 测试基础 watch ===')
const state = reactive({ count: 0, user: { name: 'Alice' } })

// 1. 基础监听
watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log(`📢 count 变化: ${oldVal} → ${newVal}`)
  }
)

console.log('修改 count:')
state.count = 1

console.log('\n=== 测试深度监听 ===')
// 2. 深度监听
watch(
  () => state.user,
  (newVal, oldVal) => {
    console.log(`📢 user 变化:`, newVal)
  },
  { deep: true }
)

console.log('修改嵌套属性:')
state.user.name = 'Bob'

console.log('\n=== 测试立即执行 ===')
// 3. 立即执行
watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log(`📢 immediate: ${oldVal} → ${newVal}`)
  },
  { immediate: true }
)

console.log('\n=== 测试 ref 监听 ===')
const countRef = ref(0)

watch(
  countRef,
  (newVal, oldVal) => {
    console.log(`📢 ref 变化: ${oldVal} → ${newVal}`)
  }
)

console.log('修改 ref:')
countRef.value = 10

console.log('\n=== 测试清理函数 ===')
// 4. 清理函数测试
let asyncOperationId = 0
watch(
  () => state.count,
  (newVal, oldVal, onInvalidate) => {
    const currentId = ++asyncOperationId
    console.log(`🔄 开始异步操作 #${currentId}, count: ${newVal}`)
    
    onInvalidate(() => {
      console.log(`🧹 清理异步操作 #${currentId}`)
    })
    
    // 模拟异步操作
    setTimeout(() => {
      // 检查是否已被清理
      if (currentId === asyncOperationId) {
        console.log(`✅ 完成异步操作 #${currentId}`)
      }
    }, 1000)
  }
)

// 快速连续修改，触发清理
setTimeout(() => state.count = 2, 100)
setTimeout(() => state.count = 3, 200)

console.log('\n=== 测试停止监听 ===')
// 5. 停止监听
const stop = watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log(`❌ 这个不应该执行: ${newVal}`)
  }
)

console.log('停止前修改:')
state.count = 100

console.log('停止监听...')
stop()

console.log('停止后修改:')
state.count = 200

console.log('\n=== 测试数组监听 ===')
// 6. 数组监听
const arr = reactive([1, 2, 3])
const ref1 = ref('a')
const ref2 = ref('b')

watch(
  [() => arr.length, ref1, ref2],
  ([newLength, newRef1, newRef2], [oldLength, oldRef1, oldRef2]) => {
    console.log(`📢 数组变化: 长度 ${oldLength}→${newLength}, ref1: ${oldRef1}→${newRef1}, ref2: ${oldRef2}→${newRef2}`)
  }
)

console.log('修改数组和ref:')
arr.push(4)
ref1.value = 'A'

console.log('\n=== 测试执行时机 ===')
// 7. 执行时机测试
watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log(`⏰ sync 同步执行: ${newVal}`)
  },
  { flush: 'sync' }
)

watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log(`⏰ post 后置执行: ${newVal}`)
  },
  { flush: 'post' }
)

console.log('测试执行时机:')
state.count = 999
console.log('同步代码执行完毕')